package MicroRpc.framework.protocol.handler;

import MicroRpc.framework.beans.Invoker;
import MicroRpc.framework.loadbalance.LoadBalance;
import MicroRpc.framework.protocol.Protocol;
import MicroRpc.framework.beans.Url;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Proxy;
@Slf4j(topic = "m.AbstractProtocolHandler")
public abstract class AbstractProtocolHandler implements Protocol {
    protected final LoadBalance loadBalance;
    public AbstractProtocolHandler(LoadBalance loadBalance) {
        this.loadBalance = loadBalance;
    }

    @Override
    public abstract Object send(Invoker invoker);

    @Override
    public abstract void recv(Url url);

    protected  <T>T getProxy(Class clazz) {
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{clazz},
                (proxy, method, args) -> {
                    Class[] argsTypes = buildTypes(args);
                    Invoker invoker = new Invoker(clazz.getName(), method.getName(), argsTypes, args);
                    Object result = send(invoker);
                    return result;
                }
        );
    }

    private Class[] buildTypes(Object[] args) {
        if (null == args || args.length==0)
            return null;
        Class[] cs=new Class[args.length];
        int i=0;
        for (Object a : args) {
            cs[i++]=a.getClass();
        }
        return cs;
    }

    @Override
    public <T> T getService(String interfaceName){
        Class clazz = null;
        try {
            clazz = ClassLoader.getSystemClassLoader().loadClass(interfaceName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return getService(clazz);
    }

    @Override
    public <T> T getService(Class clazz){
        T proxy = getProxy(clazz);
        return proxy;
    }
}
